﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Microsoft.Office.InfoPath;

namespace InfoPathDebugger.UserControls
{
    public partial class MonitorControl : UserControl
    {
        public MonitorControl()
        {
            InitializeComponent();

            initializeFieldsChangedListView();
            initializeWatchListView();
        }

        public DataSourceCollection DataSourceCollection
        {
            get
            {
                return _dsCollection;
            }
            set
            {
                Boolean isClear = (value == null);
                btnClearFieldsChangedListView.Enabled = !isClear;
                btnClearWatchListView.Enabled = !isClear;
                btnAddNewField.Enabled = !isClear;

                _dsCollection = value;
            }
        }

        public void Clear()
        {
            lstWatch.Items.Clear();
            lstChangedFields.Items.Clear();
        }

        /// <summary>
        /// Add a new field to the data fields changed list view.
        /// </summary>
        /// <param name="dataItem">A new data item.</param>
        public void UpdateFieldsChangedListView(FieldChangedListViewDataItem dataItem)
        {
            // Add new items to the list view.
            insertItemToListView(lstChangedFields, dataItem);
        }

        /// <summary>
        /// Update fields in the watch list view.
        /// </summary>
        /// <param name="dataItem">A changed data item.</param>
        public void UpdateWatchListView(FieldChangedListViewDataItem dataItem)
        {
            foreach (ListViewItem item in lstWatch.Items)
            {
                ListViewItem.ListViewSubItem pathItem = item.SubItems[1];
                if (String.Compare(pathItem.Text, dataItem.Path) == 0)
                {
                    item.SubItems[2].Text = dataItem.OldValue;
                    item.SubItems[3].Text = dataItem.NewValue;
                    item.SubItems[4].Text = dataItem.Operation;
                    item.SubItems[5].Text = dataItem.Time;

                    item.ForeColor = Color.Red;
                }
            }
        }

        private void insertItemToListView(ListView listView, FieldChangedListViewDataItem dataItem)
        {
            // Add new items to the list view.
            ListViewItem item = new ListViewItem(dataItem.Name);
            item.SubItems.Add(dataItem.Path);
            item.SubItems.Add(dataItem.OldValue);
            item.SubItems.Add(dataItem.NewValue);
            item.SubItems.Add(dataItem.Operation);
            item.SubItems.Add(dataItem.Time);

            listView.Items.Insert(0, item);
        }

        private void initializeFieldsChangedListView()
        {
            initializeView(lstChangedFields);
        }

        private void initializeWatchListView()
        {
            initializeView(lstWatch);
        }

        private void initializeView(ListView listView)
        {
            // Set styles of the list view.
            listView.GridLines = true;
            listView.ShowItemToolTips = true;
            listView.View = System.Windows.Forms.View.Details;
            listView.FullRowSelect = true;
            listView.Sorting = SortOrder.None;

            // Initialize list view columns.
            listView.Columns.Add("Name", 80);
            listView.Columns.Add("Path", 200);
            listView.Columns.Add("Old Value", 100);
            listView.Columns.Add("New Value", 100);
            listView.Columns.Add("Operation", 100);
            listView.Columns.Add("Time", 100);
        }

        private void btnClearFieldsChangedListView_Click(object sender, EventArgs e)
        {
            // Clear existing data of fields change list view
            lstChangedFields.Items.Clear();
        }

        private void btnAddNewField_Click(object sender, EventArgs e)
        {
            WatchSelectForm watchSelectForm = new WatchSelectForm();
            watchSelectForm.DataSourceCollection = _dsCollection;
            watchSelectForm.Initialize();
            
            if (DialogResult.OK == watchSelectForm.ShowDialog())
            {
                List<FieldChangedListViewDataItem> selectedItems = watchSelectForm.SelectedFields;
                foreach (FieldChangedListViewDataItem selectedItem in selectedItems)
                {
                    insertItemToListView(lstWatch, selectedItem);
                }
            }
        }

        private void btnClearWatchListView_Click(object sender, EventArgs e)
        {
            // Clear existing data of watch list view
            lstWatch.Items.Clear();
        }

        private void lstWatch_MouseClick(object sender, MouseEventArgs e)
        {
            _currentWatchListViewSelectedItemIndex = -1;

            if (e.Button == MouseButtons.Right)
            {
                conMenuWatchListView.Show(lstWatch, e.Location);

                ListViewHitTestInfo hitTestInfo = lstWatch.HitTest(e.Location);

                // Get the selected item index.
                if (hitTestInfo.Item != null)
                {
                    _currentWatchListViewSelectedItemIndex = hitTestInfo.Item.Index;
                }
            }
        }

        private void lstChangedFields_MouseClick(object sender, MouseEventArgs e)
        {
            _currentChangeListViewSelectItemText = String.Empty;

            if (e.Button == MouseButtons.Right)
            {
                conMenuChangeListView.Show(lstChangedFields, e.Location);

                ListViewHitTestInfo hitTestInfo = lstChangedFields.HitTest(e.Location);

                // Get the selected sub item
                if (hitTestInfo.SubItem != null)
                {
                    _currentChangeListViewSelectItemText = hitTestInfo.SubItem.Text;
                }
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_currentWatchListViewSelectedItemIndex != -1)
            {
                lstWatch.Items.RemoveAt(_currentWatchListViewSelectedItemIndex);
            }
        }

        private void clearChangeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_currentWatchListViewSelectedItemIndex != -1)
            {
                ListViewItem item = lstWatch.Items[_currentWatchListViewSelectedItemIndex];
                item.SubItems[2].Text = String.Empty;
                item.SubItems[3].Text = String.Empty;
                item.SubItems[4].Text = String.Empty;
                item.SubItems[5].Text = String.Empty;
                item.ForeColor = Color.Black;
            }
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(_currentChangeListViewSelectItemText))
            {
                Clipboard.SetText(_currentChangeListViewSelectItemText);
            }
        }

        private Int32 _currentWatchListViewSelectedItemIndex = -1;
        private String _currentChangeListViewSelectItemText = String.Empty;
        private DataSourceCollection _dsCollection;
    }

    /// <summary>
    /// Represents the needed data of the field changed list view.
    /// </summary>
    public class FieldChangedListViewDataItem
    {
        public String Name
        {
            get;
            set;
        }

        public String Path
        {
            get;
            set;
        }

        public String OldValue
        {
            get;
            set;
        }

        public String NewValue
        {
            get;
            set;
        }

        public String Operation
        {
            get;
            set;
        }

        public String Time
        {
            get;
            set;
        }
    }
}
